package lapsnake.workspace;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;

import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.ListCellRenderer;
import javax.swing.border.LineBorder;

import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
import org.fife.ui.rtextarea.RTextScrollPane;

import lapsnake.main.LapSnake;
import lapsnake.model.data.Property;
import lapsnake.model.data.TypedListener;
import lapsnake.model.dnd.StmtPanel;
import lapsnake.model.stmt.LapClassDef;
import lapsnake.model.stmt.LapFunctionDef;


public class ClassFrame extends JInternalFrame 
{
	private static final long serialVersionUID = 5300578578218867505L;
	final Workspace workspace;
	final LapClassDef myClass;
	
	private LapFunctionDef currentFunction = null;
	
	/**Reference to the listener which updates the text field when the model changes.
	 * This reference must be kept to prevent the listener from being garbage collected before the frame is destroyed.*/
	private TypedListener<String> areaUpdater;
	
	public ClassFrame(Workspace w, LapClassDef myClass) 
	{
		super(myClass.getName());
		this.workspace = w;
		this.myClass = myClass;
		setSize(640,480);
		setVisible(true);
		setResizable(true);
		
		JPanel tlp = new JPanel(new GridBagLayout());
		GridBagConstraints c = new GridBagConstraints(0,0,1,1,0,1,GridBagConstraints.WEST,GridBagConstraints.BOTH,new Insets(0,0,0,0), 0, 0);
		
		LapFunctionDef[] methods = myClass.getMethods();
		JList<LapFunctionDef> methodList = new JList<>(methods);
		methodList.setCellRenderer(new ListCellRenderer<LapFunctionDef>()
			{
			
			@Override
			public Component getListCellRendererComponent(
				JList<? extends LapFunctionDef> list, LapFunctionDef value,
				int index, boolean isSelected, boolean cellHasFocus)
			{
				JLabel renderer = new JLabel(value.name.get().value());
				
				if(cellHasFocus)
				{
					renderer.setBackground(methodList.getSelectionBackground());
					renderer.setForeground(methodList.getSelectionForeground());
					renderer.setOpaque(true);
				}
				else
					renderer.setForeground(methodList.getForeground());
				if(isSelected)
				{
					LineBorder b = new LineBorder(Color.BLACK, 1){
						private static final long serialVersionUID = 1999999122L;
						public Insets getBorderInsets(Component c, Insets insets) { return insets;}
					};
					renderer.setBorder(b);
				}
				
				
				return renderer;
			}
			});
		tlp.add(methodList, c);
		
		c.gridx ++;
		c.weightx = 1;
		
		JPanel codePanel = new JPanel();
		codePanel.setLayout(new BorderLayout());
		JScrollPane scrollPane = new JScrollPane(codePanel);
		tlp.add(scrollPane, c);
		
		methodList.addListSelectionListener(e -> 
		{
			generate(codePanel, methodList.getSelectedValue());		
		});
		
		RSyntaxTextArea area = new RSyntaxTextArea(20, 60);
		area.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_PYTHON);
		area.setColumns(4);
		area.setTabsEmulated(true);
		area.setTabSize(LapSnake.settings.indentSpaces.get());
		area.setText(myClass.pyAST.getScript());
		area.setAutoIndentEnabled(true);
		RTextScrollPane sp = new RTextScrollPane(area);
		areaUpdater = new TypedListener<String>() 
		{
			@Override
			public void valueChanged(Property<? extends String> property, String oldValue)
			{
				area.setText(property.get());
			}
		};
		myClass.pyAST.script.addListener(areaUpdater);
		
		//area.addLineHighlight(3, new Color(0xe5ebf0, false)); TODO highlight current class, function, action
		
		
		sp.setMinimumSize(new Dimension());
		tlp.setMinimumSize(new Dimension());
		JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, tlp, sp);
		add(split);
			split.setDividerLocation(320);
	}
	
	private void generate(JPanel codePanel, LapFunctionDef selectedValue)
	{
		if(currentFunction != selectedValue)
		{
			System.gc();//Garbage collect old ui so weakreferences to listeners on the model can be cleared
			codePanel.removeAll();
			codePanel.add(new StmtPanel(selectedValue.pyAST, selectedValue.body));
			codePanel.revalidate();
			codePanel.repaint();
			currentFunction = selectedValue;
		}
	}
}
